package com.dianpingmedia;

import com.alibaba.fastjson.JSON;
import com.dianpingmedia.common.SimulateConstant;
import com.dianpingmedia.common.utils.FormatJSONUtil;
import com.dianpingmedia.common.utils.MiscUtil;
import com.dianpingmedia.common.utils.SmlUtils;
import com.dianpingmedia.proto.ProtoZmeng;
import com.dianpingmedia.simulate.model.SimulateImpressArg;
import com.dianpingmedia.simulate.model.SimulateNotes;
import com.dianpingmedia.simulate.service.SimulateService;
import org.apache.ibatis.binding.MapperMethod;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Map;


@Component
@Aspect
public class LogAspect {

    private final Logger LOGGER = LoggerFactory.getLogger(LogAspect.class.getSimpleName());


    private ThreadLocal<SimulateNotes> simulateNotesThreadLocal = new ThreadLocal<SimulateNotes>();


    @Autowired
    SimulateService simulateService;

    @Pointcut("@annotation(org.springframework.web.bind.annotation.RequestMapping)")
    public void webLog() {
    }

    @Before("webLog()")
    public void before(JoinPoint joinPoint) throws Throwable {

        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        String requestURI = request.getRequestURI();

        simulateNotesThreadLocal.set(new SimulateNotes());
        simulateNotesThreadLocal.get().setUri(requestURI);
        Object object = joinPoint.getArgs()[0];
        switch (requestURI) {
            case SimulateConstant.UPLOAD_MATERIAL:
            case SimulateConstant.QUERY_MATERIAL:
            case SimulateConstant.PLAN_CREATE:
            case SimulateConstant.ZMT_CERTIFICATE_UPDATE:
            case SimulateConstant.ZMT_MATERIAL_PUSH:
            case SimulateConstant.IFLY_AD_REQ:
            case SimulateConstant.IFLY_MATERIAL_PUSH:
            case SimulateConstant.IFLY_MEDIA_SYNC:
            case SimulateConstant.IFLY_ADUNIT_SYNC:
                simulateNotesThreadLocal.get().setRequest(JSON.toJSONString(object));
                simulateNotesThreadLocal.get().setReturnCode(200);
                break;
            case SimulateConstant.IMPRESS_BEGIN:
            case SimulateConstant.IMPRESS_END:
            case SimulateConstant.IMPRESS_WIN:
                simulateNotesThreadLocal.get().setRequest(request.getQueryString());
                simulateNotesThreadLocal.get().setReturnCode(((SimulateImpressArg) object).getCode());
                break;
            case SimulateConstant.ZMT_AD_REQ:
                simulateNotesThreadLocal.get().setRequest(((ProtoZmeng.ZmAdRequest) object).toString());
                simulateNotesThreadLocal.get().setReturnCode(200);
                break;
            default:
                simulateNotesThreadLocal.get().setRequest(JSON.toJSONString(object));
                simulateNotesThreadLocal.get().setReturnCode(200);
                break;
        }
        LOGGER.info(requestURI + " REQUEST DATA:" + FormatJSONUtil.format(simulateNotesThreadLocal.get().getRequest()));
    }

    @AfterReturning(returning = "ret", pointcut = "webLog()")
    public void after(Object ret) throws Throwable {
        String requestURI = simulateNotesThreadLocal.get().getUri();
        String occurredTime = SmlUtils.convert(System.currentTimeMillis());
        simulateNotesThreadLocal.get().setOccurredTime(occurredTime);
        switch (requestURI) {
            case SimulateConstant.UPLOAD_MATERIAL:
            case SimulateConstant.QUERY_MATERIAL:
                simulateNotesThreadLocal.get().setType(0);
                simulateNotesThreadLocal.get().setReturnCode(200);
                simulateNotesThreadLocal.get().setResponse(JSON.toJSONString(ret));
                break;
            case SimulateConstant.PLAN_CREATE:
            case SimulateConstant.ZMT_CERTIFICATE_UPDATE:
            case SimulateConstant.ZMT_MATERIAL_PUSH:
            case SimulateConstant.IFLY_AD_REQ:
            case SimulateConstant.IFLY_MATERIAL_PUSH:
            case SimulateConstant.IFLY_MEDIA_SYNC:
            case SimulateConstant.IFLY_ADUNIT_SYNC:
                simulateNotesThreadLocal.get().setType(1);
                simulateNotesThreadLocal.get().setReturnCode(200);
                simulateNotesThreadLocal.get().setResponse(JSON.toJSONString(ret));
                break;
            case SimulateConstant.IMPRESS_BEGIN:
            case SimulateConstant.IMPRESS_END:
            case SimulateConstant.IMPRESS_WIN:
                simulateNotesThreadLocal.get().setType(1);
                LOGGER.info(requestURI + " RETURN  CODE:\n" + simulateNotesThreadLocal.get().getReturnCode());
                simulateService.recordNotes(simulateNotesThreadLocal.get());
                return;
            case SimulateConstant.ZMT_AD_REQ:
                simulateNotesThreadLocal.get().setType(1);
                simulateNotesThreadLocal.get().setResponse(((ProtoZmeng.ZmAdResponse) ret).toString());
                simulateNotesThreadLocal.get().setReturnCode(200);
                break;
            default:
                simulateNotesThreadLocal.get().setType(1);
                simulateNotesThreadLocal.get().setReturnCode(200);
                if (ret instanceof String) {
                    simulateNotesThreadLocal.get().setResponse(ret.toString());
                } else {
                    simulateNotesThreadLocal.get().setResponse(JSON.toJSONString(ret));
                }
                break;
        }

        LOGGER.info(requestURI + " RETURN  DATA:" + FormatJSONUtil.format(simulateNotesThreadLocal.get().getResponse()));
        try {
            simulateService.recordNotes(simulateNotesThreadLocal.get());
        } catch (Exception e) {
        }
//        LOGGER.info(requestURI+" Notes: " + FormatJSONUtil.format(JSON.toJSONString(simulateNotesThreadLocal.get())));
    }
}
